import { TextSplitter } from '../utils/textSplitter.js'
import { generateEmbeddings } from '../utils/embeddings.js'
import { processFile } from '../utils/fileProcessor.js'
import logger from './logger.js'
import path from 'path'
import EventEmitter from 'events'

export class DocumentProcessor extends EventEmitter {
  constructor(options = {}) {
    super()
    this.textSplitter = new TextSplitter({
      chunkSize: options.chunkSize || 1000,
      chunkOverlap: options.chunkOverlap || 200
    })
    
    // 处理队列和状态
    this.processingQueue = []
    this.isProcessing = false
    this.processingStatus = new Map()
  }

  // 获取处理状态
  getStatus(id) {
    return this.processingStatus.get(id)
  }

  // 添加文档到处理队列
  async addToQueue(file) {
    const id = file.filename
    this.processingStatus.set(id, {
      id,
      filename: file.originalname,
      status: 'pending',
      progress: 0,
      error: null,
      startTime: Date.now()
    })

    return new Promise((resolve, reject) => {
      this.processingQueue.push({
        file,
        resolve,
        reject
      })
      
      this.emit('queued', { id, filename: file.originalname })
      
      if (!this.isProcessing) {
        this.processQueue()
      }
    })
  }

  // 更新处理状态
  updateStatus(id, updates) {
    const status = this.processingStatus.get(id)
    if (status) {
      Object.assign(status, updates)
      this.emit('status-updated', status)
    }
  }

  // 处理队列中的文档
  async processQueue() {
    if (this.isProcessing || this.processingQueue.length === 0) {
      return
    }

    this.isProcessing = true
    const task = this.processingQueue.shift()
    const id = task.file.filename

    try {
      this.updateStatus(id, { status: 'processing' })
      const result = await this.processDocument(task.file)
      
      this.updateStatus(id, { 
        status: 'completed',
        progress: 100,
        endTime: Date.now()
      })
      
      task.resolve(result)
    } catch (error) {
      logger.error('文档处理失败', {
        filename: task.file.originalname,
        error: error.message
      })
      
      this.updateStatus(id, {
        status: 'failed',
        error: error.message,
        endTime: Date.now()
      })
      
      task.reject(error)
    } finally {
      this.isProcessing = false
      
      // 30分钟后清理状态
      setTimeout(() => {
        this.processingStatus.delete(id)
      }, 30 * 60 * 1000)
      
      if (this.processingQueue.length > 0) {
        this.processQueue()
      }
    }
  }

  // 处理单个文档
  async processDocument(file) {
    const id = file.filename
    const startTime = Date.now()
    
    logger.info('开始处理文档', {
      filename: file.originalname,
      size: file.size
    })

    try {
      // 1. 提取文本内容
      this.updateStatus(id, { progress: 10, stage: 'extracting' })
      const content = await processFile(file.path)
      
      // 2. 分割文本
      this.updateStatus(id, { progress: 30, stage: 'splitting' })
      const chunks = this.textSplitter.split(content)
      
      logger.debug('文档分块完成', {
        filename: file.originalname,
        chunks: chunks.length
      })

      // 3. 生成向量
      this.updateStatus(id, { progress: 50, stage: 'embedding' })
      const chunkData = await this.processChunks(file, chunks, progress => {
        this.updateStatus(id, { progress: 50 + progress * 0.4 })
      })

      const duration = Date.now() - startTime
      logger.info('文档处理完成', {
        filename: file.originalname,
        chunks: chunks.length,
        duration: `${duration}ms`
      })

      return {
        id: file.filename,
        title: file.originalname,
        size: file.size,
        type: path.extname(file.originalname).toUpperCase().slice(1),
        chunks: chunkData.length,
        duration
      }
    } catch (error) {
      logger.error('文档处理错误', {
        filename: file.originalname,
        error: error.message
      })
      throw error
    }
  }

  // 批量处理文本块
  async processChunks(file, chunks, onProgress) {
    const batchSize = 5 // 并发处理数量
    const results = []
    let completed = 0
    
    for (let i = 0; i < chunks.length; i += batchSize) {
      const batch = chunks.slice(i, i + batchSize)
      const batchPromises = batch.map(async (chunk, index) => {
        try {
          const embedding = await generateEmbeddings(chunk)
          completed++
          onProgress?.(completed / chunks.length)
          
          return {
            id: `${file.filename}_${i + index}`,
            title: file.originalname,
            content: chunk,
            embedding
          }
        } catch (error) {
          logger.error('生成向量失败', {
            filename: file.originalname,
            chunk: index,
            error: error.message
          })
          throw error
        }
      })
      
      const batchResults = await Promise.all(batchPromises)
      results.push(...batchResults)
    }
    
    return results
  }
} 